```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>分布式锁技术详解 - 技术小馆</title>
    <link href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
    <link href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', 'Tahoma', Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            color: #333;
            line-height: 1.6;
        }
        .hero {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        }
        .code-block {
            background-color: #282c34;
            border-radius: 8px;
            overflow: hidden;
        }
        .code-header {
            background-color: #1e2227;
            padding: 8px 16px;
            color: #abb2bf;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .code-body {
            padding: 16px;
            color: #abb2bf;
            font-family: 'Courier New', Courier, monospace;
            white-space: pre-wrap;
        }
        .section-card {
            transition: transform 0.3s ease, box-shadow 0.3s ease;
        }
        .section-card:hover {
            transform: translateY(-5px);
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
        }
        .highlight {
            border-left: 4px solid #667eea;
            padding-left: 16px;
            background-color: #f8fafc;
        }
        .lock-icon {
            color: #667eea;
        }
    </style>
</head>
<body class="bg-gray-50">
    <!-- Hero Section -->
    <section class="hero text-white py-20 px-4">
        <div class="container mx-auto max-w-6xl">
            <div class="flex flex-col md:flex-row items-center">
                <div class="md:w-1/2 mb-10 md:mb-0">
                    <h1 class="text-4xl md:text-5xl font-bold mb-6 leading-tight">分布式锁技术深度解析</h1>
                    <p class="text-xl mb-8 opacity-90">从本地锁到分布式锁，全面解决高并发场景下的数据一致性问题</p>
                    <div class="flex space-x-4">
                        <span class="bg-white bg-opacity-20 px-4 py-2 rounded-full text-sm font-medium">并发控制</span>
                        <span class="bg-white bg-opacity-20 px-4 py-2 rounded-full text-sm font-medium">Redis</span>
                        <span class="bg-white bg-opacity-20 px-4 py-2 rounded-full text-sm font-medium">Redisson</span>
                    </div>
                </div>
                <div class="md:w-1/2">
                    <div class="bg-white bg-opacity-20 rounded-xl p-8 backdrop-blur-sm">
                        <div class="flex items-center mb-4">
                            <i class="fas fa-lock text-3xl mr-3"></i>
                            <h3 class="text-2xl font-semibold">关键特性</h3>
                        </div>
                        <ul class="space-y-3">
                            <li class="flex items-center">
                                <i class="fas fa-check-circle mr-2"></i>
                                <span>本地锁与分布式锁对比</span>
                            </li>
                            <li class="flex items-center">
                                <i class="fas fa-check-circle mr-2"></i>
                                <span>Redis SETNX 实现方案</span>
                            </li>
                            <li class="flex items-center">
                                <i class="fas fa-check-circle mr-2"></i>
                                <span>Redisson 高级锁特性</span>
                            </li>
                            <li class="flex items-center">
                                <i class="fas fa-check-circle mr-2"></i>
                                <span>读写锁与信号量应用</span>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Main Content -->
    <div class="container mx-auto max-w-6xl px-4 py-12">
        <!-- 本地锁 Section -->
        <section class="mb-20">
            <div class="flex items-center mb-8">
                <i class="fas fa-desktop text-3xl text-blue-600 mr-4"></i>
                <h2 class="text-3xl font-bold text-gray-800">本地锁</h2>
            </div>
            <div class="grid gap-8 md:grid-cols-2">
                <div class="bg-white rounded-xl shadow-md p-6 section-card">
                    <h3 class="text-xl font-semibold mb-4 text-gray-800">本地锁简介</h3>
                    <p class="text-gray-600 mb-4">本地锁也就是单体架构中的锁，可以使用<code class="bg-gray-100 px-2 py-1 rounded">lock</code>或者<code class="bg-gray-100 px-2 py-1 rounded">synchronized</code>来实现，但是这种锁只能锁住当前服务器的资源，如果在集群的情况下就会失效。</p>
                    
                    <div class="highlight mb-6">
                        <h4 class="font-medium text-gray-800 mb-2">高并发下存在问题</h4>
                        <p class="text-gray-600">如果使用浏览器来测试不会出现问题，但是用Jemeter压测这就会发现订单和库存的数据对不上，这就是同一个接口在高并发的情况下会出现问题。</p>
                    </div>
                    
                    <div class="mb-6">
                        <div class="code-block">
                            <div class="code-header">
                                <span>Java</span>
                                <button class="text-xs bg-blue-600 px-2 py-1 rounded hover:bg-blue-700">复制代码</button>
                            </div>
                            <div class="code-body">
                                @RestController
                                @RequestMapping("/native/syn")
                                public class NativeSynController {

                                    @Autowired
                                    private StringRedisTemplate redisTemplate;

                                    private String stockKey = "seckill:%s:stock";
                                    private String orderKey = "seckill:%s:order";

                                    @PostConstruct
                                    public void init() {
                                        redisTemplate.opsForValue().set(String.format(stockKey, 10), "10");
                                    }

                                    @RequestMapping("/kill")
                                    public String kill(Integer id) throws Exception {
                                        // 1.查询秒杀商品的数量
                                        Integer stock = Integer.parseInt(redisTemplate.opsForValue().get(String.format(stockKey, id)));

                                        // 2、判断库存是否充足
                                        if (stock >= 1) {
                                            // 库存-1
                                            redisTemplate.opsForValue().decrement(String.format(stockKey, id));

                                            // 订单+1
                                            redisTemplate.opsForValue().increment(String.format(orderKey, id));

                                            return "商品抢购成功...";
                                        }
                                        return "商品抢购太火爆了，已经抢购完毕。。。";
                                    }
                                }
                            </div>
                        </div>
                    </div>
                </div>
                
                <div class="bg-white rounded-xl shadow-md p-6 section-card">
                    <h3 class="text-xl font-semibold mb-4 text-gray-800">问题原理与解决方案</h3>
                    <div class="mb-6">
                        <div class="flex items-start mb-4">
                            <div class="bg-blue-100 p-2 rounded-full mr-3">
                                <i class="fas fa-exclamation-triangle text-blue-600"></i>
                            </div>
                            <div>
                                <h4 class="font-medium text-gray-800 mb-1">并发问题原理</h4>
                                <p class="text-gray-600">假设库存就剩最后一个，此时有10个线程同时去redis查看库存数量，10个线程拿到的库存数量都是1,所以10个线程就去减库存和加库存造成了数据不一致的问题。</p>
                            </div>
                        </div>
                    </div>
                    
                    <div class="mb-6">
                        <h4 class="font-medium text-gray-800 mb-2">解决方案对比</h4>
                        <div class="grid gap-4">
                            <div class="border border-gray-200 rounded-lg p-4">
                                <div class="flex items-center mb-2">
                                    <i class="fas fa-lock lock-icon mr-2"></i>
                                    <h5 class="font-medium">同步方法</h5>
                                </div>
                                <p class="text-sm text-gray-600">使用<code class="bg-gray-100 px-1 py-0.5 rounded">synchronized</code>修饰方法，简单但性能较低</p>
                            </div>
                            <div class="border border-gray-200 rounded-lg p-4">
                                <div class="flex items-center mb-2">
                                    <i class="fas fa-lock lock-icon mr-2"></i>
                                    <h5 class="font-medium">同步代码块</h5>
                                </div>
                                <p class="text-sm text-gray-600">使用<code class="bg-gray-100 px-1 py-0.5 rounded">synchronized</code>块，粒度更细</p>
                            </div>
                            <div class="border border-gray-200 rounded-lg p-4">
                                <div class="flex items-center mb-2">
                                    <i class="fas fa-lock lock-icon mr-2"></i>
                                    <h5 class="font-medium">Lock锁</h5>
                                </div>
                                <p class="text-sm text-gray-600">使用<code class="bg-gray-100 px-1 py-0.5 rounded">ReentrantLock</code>，更灵活</p>
                            </div>
                        </div>
                    </div>
                    
                    <div class="highlight">
                        <h4 class="font-medium text-gray-800 mb-2">集群环境下问题</h4>
                        <p class="text-gray-600">本地锁在分布式的情况下是不起作用的，因为每个服务都要一把锁，这个锁只能锁住当前服务器，锁不住其他的服务器。</p>
                    </div>
                </div>
            </div>
        </section>

        <!-- 分布式锁 Section -->
        <section class="mb-20">
            <div class="flex items-center mb-8">
                <i class="fas fa-network-wired text-3xl text-purple-600 mr-4"></i>
                <h2 class="text-3xl font-bold text-gray-800">分布式锁</h2>
            </div>
            
            <div class="grid gap-8">
                <div class="bg-white rounded-xl shadow-md p-6 section-card">
                    <h3 class="text-xl font-semibold mb-4 text-gray-800">SETNX实现分布式锁</h3>
                    <p class="text-gray-600 mb-4">分布式锁的出现就是为了解决本地的锁在集群情况下失效的问题。</p>
                    
                    <div class="code-block mb-6">
                        <div class="code-header">
                            <span>Java - SETNX实现</span>
                            <button class="text-xs bg-blue-600 px-2 py-1 rounded hover:bg-blue-700">复制代码</button>
                        </div>
                        <div class="code-body">
private String lockKey = "keill-goods-lock"; // 锁

@RequestMapping("/kill")
public String kill(Integer id) throws Exception {
    // 1.加锁
    Boolean lock = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 3, TimeUnit.SECONDS);
    try {
        if (lock) {
            // 查询库存
            Integer stock = Integer.parseInt(redisTemplate.opsForValue().get(String.format(stockKey, id)));
            
            if (stock >= 1) {
                // 减库存
                redisTemplate.opsForValue().decrement(String.format(stockKey, id));
                // 加订单
                redisTemplate.opsForValue().increment(String.format(orderKey, id));
                
                return "商品抢购成功...";
            }
        } else { // 没有拿到锁
            Thread.sleep(1000);
            kill(id); // 自旋
        }
    } finally {
        // 释放锁
        redisTemplate.delete(lockKey);
    }
    return "商品抢购太火爆了...";
}
                        </div>
                    </div>
                    
                    <div class="grid md:grid-cols-2 gap-6">
                        <div>
                            <h4 class="font-medium text-gray-800 mb-2">双重锁机制</h4>
                            <p class="text-gray-600 mb-4">通过双重检查机制，可以显著提高吞吐量：</p>
                            <ul class="list-disc pl-5 text-gray-600 space-y-1">
                                <li>外层检查减少锁竞争</li>
                                <li>内层检查保证数据一致性</li>
                            </ul>
                        </div>
                        <div>
                            <h4 class="font-medium text-gray-800 mb-2">SETNX问题</h4>
                            <ul class="list-disc pl-5 text-gray-600 space-y-1">
                                <li>获取到锁的线程突然宕机，导致锁没有释放</li>
                                <li>锁超时后自动释放但任务未执行完</li>
                                <li>A线程释放了B线程的锁</li>
                            </ul>
                        </div>
                    </div>
                </div>
                
                <div class="bg-white rounded-xl shadow-md p-6 section-card">
                    <h3 class="text-xl font-semibold mb-4 text-gray-800">Lua脚本释放锁</h3>
                    <p class="text-gray-600 mb-4">分布式锁最终要保证加锁和设置过期时间是原子性，查询，对比，删除这三个操作必须保持原子性。</p>
                    
                    <div class="code-block mb-6">
                        <div class="code-header">
                            <span>Java - Lua脚本实现</span>
                            <button class="text-xs bg-blue-600 px-2 py-1 rounded hover:bg-blue-700">复制代码</button>
                        </div>
                        <div class="code-body">
// 释放锁的时候使用lua脚本来做，因为lua脚本是一个原子性的操作
String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
    "then\n" +
    "    return redis.call(\"del\",KEYS[1])\n" +
    "else\n" +
    "    return 0\n" +
    "end";
DefaultRedisScript&lt;Long&gt; longDefaultRedisScript = new DefaultRedisScript<>(script,Long.class);
Long execute = redisTemplate.execute(longDefaultRedisScript, Arrays.asList(lockKey), myValue);
if (execute > 0) {
    System.out.println("释放锁成功了。。。");
}
                        </div>
                    </div>
                    
                    <div class="mermaid mb-6">
                        graph TD
                            A[客户端尝试获取锁] --> B{锁是否可用?}
                            B -->|是| C[设置锁并开始操作]
                            B -->|否| D[等待或放弃]
                            C --> E[完成操作]
                            E --> F[释放锁]
                    </div>
                </div>
            </div>
        </section>

        <!-- Redisson Section -->
        <section class="mb-20">
            <div class="flex items-center mb-8">
                <i class="fas fa-shield-alt text-3xl text-red-600 mr-4"></i>
                <h2 class="text-3xl font-bold text-gray-800">Redisson分布式锁</h2>
            </div>
            
            <div class="grid gap-8 md:grid-cols-2">
                <div class="bg-white rounded-xl shadow-md p-6 section-card">
                    <h3 class="text-xl font-semibold mb-4 text-gray-800">Redisson简介</h3>
                    <p class="text-gray-600 mb-4">基于Redis的Redisson分布式可重入锁RLock Java对象实现了java.util.concurrent.locks.Lock接口。同时还提供了异步、反射式和RxJava2标准的接口。</p>
                    
                    <div class="bg-blue-50 border-l-4 border-blue-500 p-4 mb-6">
                        <h4 class="font-medium text-gray-800 mb-2">为什么使用Redisson?</h4>
                        <ul class="list-disc pl-5 text-gray-600 space-y-1">
                            <li>自动设置锁超时时间(默认30s)</li>
                            <li>业务未完成自动续期(看门狗机制)</li>
                            <li>每个线程锁唯一标识</li>
                            <li>基于Lua脚本实现原子操作</li>
                            <li>实现JUC的Lock接口，API一致</li>
                        </ul>
                    </div>
                    
                    <div class="code-block">
                        <div class="code-header">
                            <span>Java - Redisson基本使用</span>
                            <button class="text-xs bg-blue-600 px-2 py-1 rounded hover:bg-blue-700">复制代码</button>
                        </div>
                        <div class="code-body">
@Autowired
private RedissonClient redissonClient;

@RequestMapping("/hello")
public String hello() {
    // 1.获取一把锁
    RLock lock = redissonClient.getLock("redis-loc");
    
    // 2.加锁
    lock.lock(); // 阻塞方法，获取不到锁会一直等待
    
    try {
        // 3.执行业务代码
        Thread.sleep(2000);
    } finally {
        // 4.释放锁
        if (lock.isLocked() && lock.isHeldByCurrentThread()) {
            lock.unlock();
        }
    }
    return "hello:"+System.currentTimeMillis();
}
                        </div>
                    </div>
                </div>
                
                <div class="bg-white rounded-xl shadow-md p-6 section-card">
                    <h3 class="text-xl font-semibold mb-4 text-gray-800">高级锁特性</h3>
                    
                    <div class="mb-6">
                        <h4 class="font-medium text-gray-800 mb-2">公平锁</h4>
                        <p class="text-gray-600 mb-2">优先分配给先发出请求的线程:</p>
                        <div class="code-block">
                            <div class="code-header">
                                <span>Java - 公平锁</span>
                                <button class="text-xs bg-blue-600 px-2 py-1 rounded hover:bg-blue-700">复制代码</button>
                            </div>
                            <div class="code-body">
RLock fairLock = redisson.getFairLock("anyLock");
// 最常见的使用方法
fairLock.lock();
// 10秒钟以后自动解锁
fairLock.lock(10, TimeUnit.SECONDS);
// 尝试加锁，最多等待100秒，上锁以后10秒自动解锁
boolean res = fairLock.tryLock(100, 10, TimeUnit.SECONDS);
...
fairLock.unlock();
                            </div>
                        </div>
                    </div>
                    
                    <div class="mb-6">
                        <h4 class="font-medium text-gray-800 mb-2">读写锁</h4>
                        <p class="text-gray-600 mb-2">允许多个读锁和一个写锁:</p>
                        <div class="code-block">
                            <div class="code-header">
                                <span>Java - 读写锁</span>
                                <button class="text-xs bg-blue-600 px-2 py-1 rounded hover:bg-blue-700">复制代码</button>
                            </div>
                            <div class="code-body">
RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock");
// 获取读锁
rwlock.readLock().lock();
// 获取写锁
rwlock.writeLock().lock();
                            </div>
                        </div>
                    </div>
                    
                    <div class="grid grid-cols-2 gap-4">
                        <div>
                            <h4 class="font-medium text-gray-800 mb-2">信号量</h4>
                            <div class="code-block">
                                <div class="code-body text-xs">
RSemaphore semaphore = redisson.getSemaphore("semaphore");
semaphore.acquire();
semaphore.release();
                                </div>
                            </div>
                        </div>
                        <div>
                            <h4 class="font-medium text-gray-800 mb-2">闭锁</h4>
                            <div class="code-block">
                                <div class="code-body text-xs">
RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch");
latch.trySetCount(1);
latch.await();
latch.countDown();
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <!-- 对比总结 Section -->
        <section class="mb-20">
            <div class="flex items-center mb-8">
                <i class="fas fa-balance-scale text-3xl text-green-600 mr-4"></i>
                <h2 class="text-3xl font-bold text-gray-800">技术对比与总结</h2>
            </div>
            
            <div class="bg-white rounded-xl shadow-md overflow-hidden">
                <div class="overflow-x-auto">
                    <table class="min-w-full divide-y divide-gray-200">
                        <thead class="bg-gray-50">
                            <tr>
                                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">锁类型</th>
                                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">适用场景</th>
                                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">优点</th>
                                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">缺点</th>
                            </tr>
                        </thead>
                        <tbody class="bg-white divide-y divide-gray-200">
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">本地锁</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">单体应用</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">实现简单，性能高</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">无法解决分布式问题</td>
                            </tr>
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">SETNX</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">简单分布式场景</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">基于Redis，实现相对简单</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">需要处理锁续期、误删等问题</td>
                            </tr>
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">Redisson</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">复杂分布式场景</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">功能全面，自动续期，多种锁类型</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">引入额外依赖，学习成本略高</td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
            
            <div class="mt-8 bg-blue-50 border-l-4 border-blue-500 p-6 rounded-lg">
                <h3 class="text-xl font-semibold mb-4 text-gray-800">最佳实践建议</h3>
                <ul class="list-disc pl-5 text-gray-600 space-y-2">
                    <li>单体应用优先考虑本地锁</li>
                    <li>简单分布式场景可使用SETNX+Lua</li>
                    <li>复杂分布式系统推荐使用Redisson</li>
                    <li>读写分离场景使用读写锁提高性能</li>
                    <li>注意设置合理的锁超时时间</li>
                    <li>确保锁的释放操作在finally块中执行</li>
                </ul>
            </div>
        </section>
    </div>

    <!-- Footer -->
    <footer class="bg-gray-900 text-white py-8">
        <div class="container mx-auto max-w-6xl px-4">
            <div class="flex flex-col md:flex-row justify-between items-center">
                <div class="mb-4 md:mb-0">
                    <h3 class="text-xl font-bold">技术小馆</h3>
                    <p class="text-gray-400 mt-1">专注于技术分享与学习</p>
                </div>
                <div>
                    <a href="http://www.yuque.com/jtostring" class="text-blue-400 hover:text-blue-300 transition duration-300">http://www.yuque.com/jtostring</a>
                </div>
            </div>
            <div class="border-t border-gray-800 mt-6 pt-6 text-center text-gray-500 text-sm">
                &copy; 2023 技术小馆. All rights reserved.
            </div>
        </div>
    </footer>

    <script>
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            flowchart: {
                useMaxWidth: true,
                htmlLabels: true,
                curve: 'basis'
            }
        });
    </script>
</body>
</html>
```